home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK1.toast / Development Kits / Control Strip / Control Strip Sample / ControlStripSample.c next >
Encoding:
C/C++ Source or Header  |  1994-09-14  |  10.3 KB  |  336 lines  |  [TEXT/MPS ]

  1. /********************************************************************************************
  2.  
  3.     file:        ControlStripSample.c
  4.  
  5.     contains:    a sample Control Strip module
  6.  
  7.     author:        SC        [8/29/93]
  8.     modified:    DTS        06/07/94        rename files, comments to reflect name is
  9.                                         Control Strip (as opposed to Status Bar)
  10.  
  11.     Copyright © 1993 by Apple Computer, Inc.  All rights reserved.
  12.  
  13. ********************************************************************************************/
  14.  
  15. #ifndef  SystemSevenOrLater
  16. #define  SystemSevenOrLater    1
  17. #endif
  18.  
  19. #include <Memory.h>
  20. #include <Menus.h>
  21. #include <Quickdraw.h>
  22. #include <Resources.h>
  23. #include <ToolUtils.h>
  24. #include <Types.h>
  25. #include <Icons.h>
  26. #include "ControlStrip.h"
  27. #include "ControlStripSample.h"
  28.  
  29.  
  30. //////////////////////////////////////////////////////////////////////////////////////////////
  31. //
  32. //    global variables
  33.  
  34. typedef struct Globals {                                // global variables we use while we exist
  35.     Handle            lastIcon;                            //    last icon to be displayed
  36.     Handle            firstIcon;                            //    icon suites displayed in the Control Strip module
  37.     Handle            secondIcon;
  38.     Handle            thirdIcon;
  39.     PicHandle        popupArrowPicture;                    //    picture to show we have a popup menu
  40.     Handle            helpStrings;                        //    balloon help strings for each state
  41.     short            helpStringIndex;                    //    which help string to display
  42.     short            whichIcon;                            //    which icon we're drawing
  43.     MenuHandle        configMenu;                            //    menu to select display options
  44. } Globals;
  45.  
  46.  
  47. //////////////////////////////////////////////////////////////////////////////////////////////
  48. //
  49. //    information saved across restarts
  50.  
  51. typedef struct SavedSettings {
  52.     OSType            signature;                            //    signature to verify it's for this module
  53.     short            whichIcon;                            //    which icon we're drawing
  54. } SavedSettings;
  55.  
  56.  
  57. //////////////////////////////////////////////////////////////////////////////////////////////
  58. //
  59. //    prototypes
  60.  
  61. long Initialize();
  62. void CleanUp(Globals **globs);
  63. void DrawCurrentIcon(Globals *gb, Rect *statusRect);
  64. void GetCurrentIcon(Globals *gb);
  65. long HandleMouseClick(Globals *gb, Rect *statusRect);
  66. short SavePreferences(Globals *gb);
  67.  
  68.  
  69.  
  70. //////////////////////////////////////////////////////////////////////////////////////////////
  71. //
  72. //    entry point
  73.  
  74. pascal long main(unsigned long message, Globals **globs, Rect *statusRect, GrafPtr statusPort) {
  75. #pragma unused(statusPort)
  76.     char            savedState;
  77.     Globals            *gb;
  78.     long            result;
  79.     Handle            theLastIcon;
  80.     Str255            helpString;
  81.  
  82.  
  83.     if ((long)globs > 0) {                                // if we have globals allocated,
  84.         savedState = HGetState((Handle)globs);            //    save the locked/unlocked state,
  85.         HLock((Handle)globs);                            //    lock the handle to the globals,
  86.         gb = *globs;                                    //    and point to the globals directly
  87.     }
  88.  
  89.     result = 0;                                            // just return zero for unknown messages
  90.     switch(message) {
  91.         case sdevInitModule:                            // initialize the module
  92.             if ((result = Initialize()) > 0) break;        //  and exit if successful
  93.             globs = (Globals **)result;
  94.  
  95.         case sdevCloseModule:                            // clean up before being closed
  96.             CleanUp(globs);
  97.             globs = 0L;
  98.             break;
  99.  
  100.         case sdevFeatures:                                // return feature bits
  101.             result = (1<<sdevWantMouseClicks)    |\
  102.                      (1<<sdevDontAutoTrack)        |\
  103.                      (1<<sdevHasCustomHelp);
  104.             break;
  105.  
  106.         case sdevGetDisplayWidth:                        // return display width
  107.             result = IconWidth +
  108.                         (**gb->popupArrowPicture).picFrame.right - (**gb->popupArrowPicture).picFrame.left;
  109.             break;
  110.  
  111.         case sdevPeriodicTickle:                        // periodic tickle when nothing else is happening
  112.             theLastIcon = gb->lastIcon;                    //    save the last state
  113.             GetCurrentIcon(gb);                            //    update everything
  114.             if (theLastIcon == gb->lastIcon) break;        //    if everything's the same, just exit
  115.             result += 1<<sdevHelpStateChange;            //    flag a state change in case we're displaying help
  116.  
  117.             statusRect->right = statusRect->left + IconWidth;
  118.             EraseRect(statusRect);                        // erase the icon
  119.  
  120.         case sdevDrawStatus:                            // update the interface in the Control Strip
  121.             DrawCurrentIcon(gb, statusRect);
  122.             break;
  123.  
  124.         case sdevMouseClick:                            // user clicked on the module's display area in the Control Strip
  125.             result = HandleMouseClick(gb, statusRect);
  126.             break;
  127.  
  128.         case sdevSaveSettings:                            // save changed settings
  129.             result = SavePreferences(gb);
  130.             break;
  131.  
  132.         case sdevShowBalloonHelp:                        // display custom balloon help
  133.             SBGetDetachedIndString(helpString, gb->helpStrings, gb->helpStringIndex);
  134.             SBShowHelpString(statusRect, helpString);
  135.             break;
  136.     }
  137.  
  138.     if ((long)globs > 0)                                // if we have globals allocated,
  139.         HSetState((Handle)globs, savedState);            //    restore the locked/unlocked state
  140.  
  141.     return(result);
  142. }
  143.  
  144.  
  145. //////////////////////////////////////////////////////////////////////////////////////////////
  146. //
  147. //    initializes the module
  148.  
  149. long Initialize() {
  150.     short            i;
  151.     long            result;
  152.     Globals            **globs, *gb;
  153.     Str255            prefsResourceName;
  154.     SavedSettings    **preferences;
  155.     Handle            *theIconSuite;
  156.  
  157.     result = -1;                                        // assume failure
  158.  
  159.     if (! (globs = (Globals **)NewHandleClear(sizeof(Globals))))
  160.         return(MemError());                                // allocate the globals
  161.  
  162.     HLock((Handle)globs);                                // lock the globals while using them
  163.     gb = *globs;                                        //  and get a pointer to them
  164.  
  165. //    load and detach the icon suites
  166.  
  167.     theIconSuite = &gb->firstIcon;
  168.     for (i=ThirdIconID-FirstIconID; i>=0; i--) {
  169.         if (result = SBGetDetachIconSuite(theIconSuite, ThirdIconID-i, svAllSmallData))
  170.             goto done;
  171.         theIconSuite++;
  172.     }
  173.  
  174. //    load and detach the ‘up arrow’ picture
  175.  
  176.     if (! (gb->popupArrowPicture = GetPicture(PopupArrowPictID))) goto done;
  177.     DetachResource((Handle)gb->popupArrowPicture);
  178.  
  179. //    load and detach the configuration menu
  180.  
  181.     if (! (gb->configMenu = GetMenu(ConfigMenuID))) goto done;
  182.     DetachResource((Handle)gb->configMenu);
  183.  
  184. //    load and detach the help strings
  185.  
  186.     if (! (gb->helpStrings = Get1Resource('STR#', HelpStringsID))) goto done;
  187.     DetachResource(gb->helpStrings);
  188.  
  189. //    get the module's saved preferences, if any, and configure the module
  190.  
  191.     gb->whichIcon = mShowFirstIcon;
  192.     SBGetDetachedIndString(prefsResourceName, gb->helpStrings, sPrefResourceName);
  193.     if (! SBLoadPreferences(prefsResourceName, (Handle *)&preferences) &&
  194.         ((**preferences).signature == 'Samp'))
  195.         gb->whichIcon = (**preferences).whichIcon;
  196.  
  197.     GetCurrentIcon(gb);                                    // initialize which icon to draw
  198.  
  199.     HUnlock((Handle)globs);                                // unlock the globals
  200.  
  201.     result = (long)globs;                                // return the handle to the globals as the result
  202.  
  203. done:
  204.     return(result);                                        // return either a handle or an error code
  205. }
  206.  
  207.  
  208. //////////////////////////////////////////////////////////////////////////////////////////////
  209. //
  210. //    disposes of our storage before we get closed
  211.  
  212. void CleanUp(Globals **globs) {
  213.     Globals            *gb;
  214.  
  215.     if ((long)globs <= 0) return;
  216.  
  217.     HLock((Handle)globs);
  218.     gb = *globs;
  219.  
  220.     if (gb->firstIcon) DisposeIconSuite(gb->firstIcon, true);
  221.     if (gb->secondIcon) DisposeIconSuite(gb->secondIcon, true);
  222.     if (gb->thirdIcon) DisposeIconSuite(gb->thirdIcon, true);
  223.  
  224.     if (gb->popupArrowPicture) DisposeHandle((Handle)gb->popupArrowPicture);
  225.  
  226.     if (gb->configMenu) DisposeMenu(gb->configMenu);
  227.  
  228.     if (gb->helpStrings) DisposeHandle(gb->helpStrings);
  229.  
  230.     DisposeHandle((Handle)globs);
  231. }
  232.  
  233.  
  234. //////////////////////////////////////////////////////////////////////////////////////////////
  235. //
  236. //    draws the current icon
  237.  
  238. void DrawCurrentIcon(Globals *gb, Rect *statusRect) {
  239.     short            arrowHeight;
  240.  
  241. //    draw the current icon
  242.  
  243.     statusRect->right = statusRect->left + IconWidth;
  244.     (void) PlotIconSuite(statusRect, atNone, ttNone, gb->lastIcon);
  245.  
  246. //    draw an ‘up arrow’ to show that the module has a popup menu
  247.  
  248.     arrowHeight = (**gb->popupArrowPicture).picFrame.bottom - (**gb->popupArrowPicture).picFrame.top;
  249.     statusRect->left = statusRect->right;
  250.     statusRect->right += (**gb->popupArrowPicture).picFrame.right - (**gb->popupArrowPicture).picFrame.left;
  251.     statusRect->top = (statusRect->top + statusRect->bottom - arrowHeight) >> 1;
  252.     statusRect->bottom = statusRect->top + arrowHeight;
  253.     DrawPicture(gb->popupArrowPicture, statusRect);
  254. }
  255.  
  256.  
  257. //////////////////////////////////////////////////////////////////////////////////////////////
  258. //
  259. //    stuffs the icon suite handle of the current icon into gb->lastIcon,
  260. //    and the related help STR# index into gb->helpStringIndex
  261.  
  262. void GetCurrentIcon(Globals *gb) {
  263.  
  264.     switch (gb->whichIcon) {
  265.         case mShowFirstIcon:
  266.             gb->lastIcon = gb->firstIcon;
  267.             gb->helpStringIndex = sFirstIconHelp;
  268.             break;
  269.  
  270.         case mShowSecondIcon:
  271.             gb->lastIcon = gb->secondIcon;
  272.             gb->helpStringIndex = sSecondIconHelp;
  273.             break;
  274.  
  275.         case mShowThirdIcon:
  276.             gb->lastIcon = gb->thirdIcon;
  277.             gb->helpStringIndex = sThirdIconHelp;
  278.             break;
  279.     }
  280. }
  281.  
  282.  
  283. //////////////////////////////////////////////////////////////////////////////////////////////
  284. //
  285. //    handles a mouse click on the module's display by tracking a popup menu to change settings
  286.  
  287. long HandleMouseClick(Globals *gb, Rect *statusRect) {
  288.     short            menuItem;
  289.     long            result;
  290.  
  291.     SetItemMark(gb->configMenu, gb->whichIcon, sdevMenuItemMark);
  292.                                                     // check the item for the current icon
  293.  
  294.     menuItem = SBTrackPopupMenu(statusRect, gb->configMenu);
  295.                                                     // call the utility routine to display a popup menu
  296.  
  297.     CheckItem(gb->configMenu, gb->whichIcon, false);// uncheck the item for the previous icon
  298.  
  299.     result = 0;
  300.     if ((menuItem > 0) && (menuItem != gb->whichIcon)) {
  301.                                                     // if something was selected,
  302.         gb->whichIcon = menuItem;                    //    save the menu item number,
  303.         GetCurrentIcon(gb);                            //     update the icon,
  304.         result = 1<<sdevNeedToSave;                    //     and notify the Control Strip that we need to update preferences
  305.     }
  306.  
  307.     return(result);
  308. }
  309.  
  310.  
  311. //////////////////////////////////////////////////////////////////////////////////////////////
  312. //
  313. //    saves the module's settings so they'll be available across restarts
  314.  
  315. short SavePreferences(Globals *gb) {
  316.     short            result;
  317.     SavedSettings    **preferences;
  318.     Str255            prefsResourceName;
  319.  
  320.     preferences = (SavedSettings**)NewHandle(sizeof(SavedSettings));
  321.     if (! (result = MemError())) {                    // allocate a block to hold the settings
  322.  
  323.         (**preferences).signature = 'Samp';            // include a signature to verify it's ours
  324.         (**preferences).whichIcon = gb->whichIcon;    // stuff in the menu item number of the current icon
  325.  
  326.         SBGetDetachedIndString(prefsResourceName, gb->helpStrings, sPrefResourceName);
  327.                                                     // get the name of the preferences resource
  328.         result = SBSavePreferences(prefsResourceName, (Handle)preferences);
  329.                                                     // save the settings in the Control Strip's preferences file
  330.  
  331.         DisposeHandle((Handle)preferences);            // get rid of the block
  332.     }
  333.  
  334.     return(result);
  335. }
  336.